package utils

import (
	"GOPAAS/configs/config"
	"GOPAAS/internal/app/global"
	"bytes"
	"crypto/md5"
	"database/sql"
	b64 "encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"io"
	"math"
	"math/rand"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"
)

type Res struct {
	Errcode int         `json:"errcode"`
	Errmsg  string      `json:"errmsg"`
	Data    interface{} `json:"data"`
	Message string      `json:"message"`
}
type TableRes struct {
	Errcode         int         `json:"errcode"`
	Data            interface{} `json:"data"`
	RecordsTotal    int64       `json:"record_total"`
	RecordsFiltered int64       `json:"record_filtered"`
	Message         string      `json:"message"`
}

func Success(c *gin.Context, message string, data interface{}) {
	c.PureJSON(200, Res{0, "ok", data, message})
}
func Error(c *gin.Context, errcode int, message string, data interface{}) {
	c.AsciiJSON(200, Res{errcode, "no", data, message})
	ErrorLog(c, message)
}
func Table(c *gin.Context, count int64, list interface{}, errcode int, message string) {
	c.AsciiJSON(200, TableRes{errcode, list, count, count, message})
}
func HttpError(c *gin.Context, httpcode int, message string, data interface{}) {
	c.AsciiJSON(httpcode, Res{httpcode, "请求失败", data, message})
	ErrorLog(c, message)
}
func SetCorsHeader(c *gin.Context) {
	c.Header("Access-Control-Allow-Origin", "*")
	c.Header("Access-Control-Allow-Headers", "Origin,Content-Type,Cookie,X-CSRF-TOKEN,Accept,Authorization,Access-Control-Allow-Origin")
	c.Header("Access-Control-Expose-Headers", "Authorization,authenticated")
	c.Header("Access-Control-Allow-Headers", "access-control-allow-origin,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,company_id,user_id,lang,access_token")
	c.Header("Access-Control-Allow-Methods", "GET,POST,PATCH,PUT,OPTIONS")
	c.Header("Access-Control-Allow-Credentials", "true")
}
func InfoLog(c *gin.Context, msg interface{}) {
	log(c, msg, "info")
}
func PanicLog(c *gin.Context, msg interface{}) {
	log(c, msg, "Panic")
}
func FatalLog(c *gin.Context, msg interface{}) {
	log(c, msg, "Fatal")
}
func ErrorLog(c *gin.Context, msg interface{}) {
	log(c, msg, "Error")
}
func WarnLog(c *gin.Context, msg interface{}) {
	log(c, msg, "Warn")
}
func DebugLog(c *gin.Context, msg interface{}) {
	log(c, msg, "Debug")
}
func TraceLog(c *gin.Context, msg interface{}) {
	log(c, msg, "Trace")
}

// log封装日志方法
func log(c *gin.Context, msg interface{}, level string) {
	access_token, _ := c.Get("access_token")
	user_id, _ := c.Get("user_id")
	company_id, _ := c.Get("company_id")
	var content string
	switch msg.(type) {
	case string:
		content = msg.(string)
	default:
		content_byte, _ := json.Marshal(msg)
		content = string(content_byte)
	}
	b := c.Request.Body
	body, _ := io.ReadAll(b)
	c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
	body_str := string(body)
	if len(body_str) > 9999 {
		body_str = body_str[0:9999]
	}
	logField := logrus.WithFields(logrus.Fields{
		"path":         c.Request.RequestURI,
		"access_token": access_token,
		"company_id":   company_id,
		"user_id":      user_id,
		"ip":           c.ClientIP(),
		"body":         body_str,
	})
	level = strings.ToLower(level)
	switch level {
	case "panic":
		logField.Panic(content)
	case "fatal":
		logField.Fatal(content)
	case "error":
		logField.Error(content)
	case "warn":
		logField.Warn(content)
	case "debug":
		logField.Debug(content)
	case "trace":
		logField.Trace(content)
	default:
		logField.Info(content)
	}
}

func GetStructNameByModel(model string) string {
	s_arr := strings.Split(model, ".")
	var struct_name string
	for _, v := range s_arr {
		struct_name += strings.ToUpper(v[0:1])
		struct_name += v[1:]
	}
	return struct_name
}
func GetTableNameByModel(model string) string {
	return strings.ReplaceAll(model, ".", "_")
}
func StringInArray(arr []string, needle string) bool {
	for _, v := range arr {
		if v == needle {
			return true
		}
	}
	return false
}
func Int64InArray(arr []int64, needle int64) bool {
	for _, v := range arr {
		if v == needle {
			return true
		}
	}
	return false
}
func IntInArray(arr []int, needle int) bool {
	for _, v := range arr {
		if v == needle {
			return true
		}
	}
	return false
}

func GetMapIndexStr(mapData map[string]interface{}, index string) string {
	item := mapData[index]
	switch item.(type) {
	case int64:
		return strconv.Itoa(int(item.(int64)))
	case int:
		return strconv.Itoa(item.(int))
	case int32:
		return strconv.Itoa(int(item.(int32)))
	case int8:
		return strconv.Itoa(int(item.(int8)))
	case int16:
		return strconv.Itoa(int(item.(int16)))
	case string:
		return item.(string)
	default:
		return ""
	}
}
func GetUuid(codeLen int, salt int) string {
	rawStr := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-"
	// 2. 定义一个buf，并且将buf交给bytes往buf中写数据
	buf := make([]byte, 0, codeLen)
	b := bytes.NewBuffer(buf)
	// 随机从中获取
	rand.Seed(time.Now().UnixNano())
	for rawStrLen := len(rawStr); codeLen > 1; codeLen-- {
		randNum := rand.Intn(rawStrLen)
		b.WriteByte(rawStr[randNum])
	}
	b.WriteByte(rawStr[salt%62])
	return b.String()
}
func GetToken() string {
	return GetRandStringSplice(8) + "-" + GetRandStringSplice(4) + "-" + GetRandStringSplice(4) + "-" + GetRandStringSplice(4) + "-" + GetRandStringSplice(8)
}

// GetRandStringSplice 随机获取字符串中组成的新串
func GetRandStringSplice(length int) string {
	// 2. 定义一个buf，并且将buf交给bytes往buf中写数据
	buf := make([]byte, 0, length)
	b := bytes.NewBuffer(buf)
	rawStr := "abcdefghijklmnopqrstuvwxyz0123456789"
	rand.Seed(time.Now().UnixNano())
	for i := 0; i < length; i++ {
		randNum := rand.Intn(len(rawStr))
		b.WriteByte(rawStr[randNum])
	}
	return b.String()
}

// GetVerifyCode 验证码
func GetVerifyCode(codeLen int) string {
	rawStr := "0123456789"
	// 2. 定义一个buf，并且将buf交给bytes往buf中写数据
	buf := make([]byte, 0, codeLen)
	b := bytes.NewBuffer(buf)
	// 随机从中获取
	rand.Seed(time.Now().UnixNano())
	for rawStrLen := len(rawStr); codeLen > 0; codeLen-- {
		randNum := rand.Intn(rawStrLen)
		b.WriteByte(rawStr[randNum])
	}
	return b.String()
}
func GetAppid() string {
	str := time.Now().Format("20060102150405")
	rand.Seed(time.Now().UnixNano())
	randStr := strconv.Itoa(rand.Intn(99))
	return str + randStr
}

// GetAccessToken 获取access_token
func GetAccessToken(login string, appid string, secret string) string {
	API_SECRET := "dtcloud"
	today := time.Now().Format("2006-01-02")
	encryt_slice := md5.Sum([]byte(login + appid + secret + today + API_SECRET))
	return fmt.Sprintf("%x", encryt_slice)
}

// GetStructoToMap 结构体转map
func GetStructoToMap(param interface{}, data interface{}) {
	str, _ := json.Marshal(param)
	_ = json.Unmarshal(str, &data)
}

// RecentDates 最近几天日期
func RecentDates(n int) []time.Time {
	var now = time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 0, 0, 0, time.Local)
	var result = make([]time.Time, 0)
	for i := 1; i <= n; i++ {
		result = append(result, now)
		now = now.AddDate(0, 0, -1)
	}
	return result
}

// GetSFZBirthDate 获取身份证里的出生日期
func GetSFZBirthDate(sfz string) time.Time {
	var birth_str string
	if len(sfz) == 15 {
		birth_str = "19" + sfz[6:12]
	} else {
		birth_str = sfz[6:14]
	}
	res, _ := time.ParseInLocation("20060102", birth_str, time.Local)
	return res
}

// CheckPasswordValid 判断密码合法
func CheckPasswordValid(password string) bool {
	if len(password) >= 8 && len(password) <= 16 {
		if res, _ := regexp.MatchString(`\w+`, password); res {
			if res1, _ := regexp.MatchString(`\d+`, password); res1 {
				return true
			}
			if res2, _ := regexp.MatchString(`[\W\D]`, password); res2 {
				return true
			}
		} else {
			if res1, _ := regexp.MatchString(`\d+`, password); res1 {
				if res2, _ := regexp.MatchString(`[\W\D]`, password); res2 {
					return true
				}
			}
		}
	}
	return false
}

// Md5 返回一个32位md5加密后的字符串
func Md5(str string) string {
	h := md5.New()
	h.Write([]byte(str))
	return hex.EncodeToString(h.Sum(nil))
}

func Base64(data []byte) string {
	return b64.StdEncoding.EncodeToString(data)
}

// LastMonths 最近几个月
func LastMonths(n int) []time.Time {
	var month_arr = make([]time.Time, 0)
	timeNow := time.Now()
	for i := 0; i < n; i++ {
		//上个月时间戳
		timeMonth := timeNow.Format("200601") + "01"
		tim, _ := time.Parse("20060102", timeMonth) //本月1号时间戳
		month_arr = append(month_arr, tim)
		lastTimeNow := tim.Unix() - 24*2*3600
		timeNow = time.Unix(lastTimeNow, 0)
	}
	return month_arr
}

// GetRangeDays 获取日期间所有日期
func GetRangeDays(start_date time.Time, end_time time.Time) []string {
	var date []string
	for i := start_date; !i.After(end_time); i = i.AddDate(0, 0, 1) {
		date = append(date, i.Format("2006-01-02"))
	}
	return date
}

// ReverseStringSlice 反转日期数组
func ReverseStringSlice(slice *[]time.Time) {
	length := len(*slice)
	var temp time.Time
	for i := 0; i < length/2; i++ {
		temp = (*slice)[i]
		(*slice)[i] = (*slice)[length-1-i]
		(*slice)[length-1-i] = temp
	}
}

// HttpGet get请求
func HttpGet(url_path string, param map[string]string, header map[string]string) (body []byte, err error) {
	var netClient = &http.Client{
		Timeout: time.Second * 30,
	}
	q := url.Values{}
	for k, v := range param {
		q.Add(k, v)
	}
	reader_data := bytes.NewReader([]byte{})
	request, err := http.NewRequest("GET", url_path, reader_data)
	request.URL.RawQuery = q.Encode()
	for k, v := range header {
		request.Header.Set(k, v)
	}
	// get
	response, err := netClient.Do(request)
	if err != nil {
		return
	}
	defer response.Body.Close()
	fmt.Println(response.StatusCode)
	//记录日志
	logField := logrus.WithFields(logrus.Fields{
		"path":     url_path,
		"param":    param,
		"status":   response.StatusCode,
		"response": body,
	})
	if response.StatusCode == 200 {
		body, err = io.ReadAll(response.Body)
		fmt.Println(string(body))
		logField.Info("请求成功")
		return
	}
	logField.Error("GET请求失败")
	err = errors.New("请求失败，状态码为：" + strconv.Itoa(response.StatusCode))
	return
}

// HttpPost post请求
func HttpPost(url_path string, header map[string]string, param map[string]string, data map[string]string) (body []byte, err error) {
	var netClient = &http.Client{
		Timeout: time.Second * 30,
	}
	var va = url.Values{}
	for k, v := range data {
		va.Add(k, v)
	}
	ctype, exist := header["Content-Type"]
	var request *http.Request
	if exist && strings.Contains(ctype, "application/json") {
		jdata, _ := json.Marshal(data)
		reader_data := bytes.NewReader(jdata)
		request, err = http.NewRequest("POST", url_path, reader_data)
	} else {
		var reader_data = strings.NewReader(va.Encode())
		request, err = http.NewRequest("POST", url_path, reader_data)
	}
	q := request.URL.Query()
	for k, v := range param {
		q.Add(k, v)
	}
	request.URL.RawQuery = q.Encode()
	if len(header) == 0 {
		request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	} else {
		for k, v := range header {
			request.Header.Set(k, v)
		}
	}
	response, err := netClient.Do(request)
	if err != nil {
		return
	}
	defer response.Body.Close()
	fmt.Println(response.StatusCode)
	logField := logrus.WithFields(logrus.Fields{
		"path":     url_path,
		"header":   header,
		"param":    param,
		"body":     data,
		"status":   response.StatusCode,
		"response": body,
	})
	if response.StatusCode == 200 {
		body, err = io.ReadAll(response.Body)
		fmt.Println(string(body))
		logField.Info("请求成功")
		return
	}
	fmt.Println(string(body))
	logField.Error("Post请求失败")
	err = errors.New("请求失败，状态码为：" + strconv.Itoa(response.StatusCode))
	return
}
func HttpPostJson(url_path string, header map[string]string, param map[string]string, data interface{}) (body []byte, err error) {
	var netClient = &http.Client{
		Timeout: time.Second * 30,
	}
	var request *http.Request
	jdata, _ := json.Marshal(data)
	reader_data := bytes.NewReader(jdata)
	request, err = http.NewRequest("POST", url_path, reader_data)
	q := request.URL.Query()
	for k, v := range param {
		q.Add(k, v)
	}
	request.URL.RawQuery = q.Encode()
	if len(header) == 0 {
		request.Header.Set("Content-Type", "application/json")
	} else {
		for k, v := range header {
			request.Header.Set(k, v)
		}
	}
	response, err := netClient.Do(request)
	if err != nil {
		return
	}

	defer response.Body.Close()
	fmt.Println(response.StatusCode)
	body, err = io.ReadAll(response.Body)
	//记录日志
	logField := logrus.WithFields(logrus.Fields{
		"path":     url_path,
		"header":   header,
		"param":    param,
		"body":     data,
		"status":   response.StatusCode,
		"response": string(body),
	})
	if response.StatusCode == 200 {
		fmt.Println(string(body))
		logField.Info("请求成功")
		return
	}
	fmt.Println(string(body))
	logField.Error("postJson请求失败")
	err = errors.New("请求失败，状态码为：" + strconv.Itoa(response.StatusCode))
	return
}
func GetQuarter(t time.Time) int {
	month := t.Month()
	switch month {
	case 1, 2, 3:
		return 1
	case 4, 5, 6:
		return 2
	case 7, 8, 9:
		return 3
	case 10, 11, 12:
		return 4
	default:
		return 0
	}
}
func GetWeekIndex(week string) int {
	switch week {
	case "Monday":
		return 1
	case "Tuesday":
		return 2
	case "Wednesday":
		return 3
	case "Thursday":
		return 4
	case "Friday":
		return 5
	case "Saturday":
		return 6
	case "Sunday":
		return 7
	default:
		return 0
	}
}

// Round 保留小数
func Round(num float64, size int) float64 {
	fmt_string := fmt.Sprintf("%%.%df", size)
	num, _ = strconv.ParseFloat(fmt.Sprintf(fmt_string, num), 64)
	return num
}

// HidePhone 隐藏手机号
func HidePhone(phone string) string {
	if len(phone) < 11 {
		return phone
	}
	return phone[0:3] + strings.Repeat("*", 4) + phone[7:11]
}

// BeautifyDate 美化日期
func BeautifyDate(dateTime time.Time) string {
	now := time.Now()
	month := now.Month()
	day := now.Day()
	year := now.Year()
	dateTime = ForceCorrectTime(dateTime)
	now_timestamp := now.Unix()
	c_month := dateTime.Month()
	c_day := dateTime.Day()
	c_year := dateTime.Year()
	c_timestamp := dateTime.Unix()
	var unit string
	var num int
	if year-c_year >= 2 || (year-c_year == 1 && month >= c_month) {
		unit = "年前"
		if month >= c_month {
			num = year - c_year
		} else {
			num = year - c_year - 1
		}
	} else if year == c_year && month-c_month > 2 || (year == c_year && month-c_month == 1 && day > c_day) || year > c_year {
		unit = "月前"
		if year == c_year {
			num = int(month - c_month)
		} else {
			num = int(month + 12 - c_month)
		}
	} else {
		if now_timestamp-c_timestamp > 24*3600 {
			unit = "天前"
			num = int(math.Floor(float64(now_timestamp-c_timestamp) / (24 * 3600)))
		} else if now_timestamp-c_timestamp > 3600 {
			unit = "小时前"
			num = int(math.Floor(float64(now_timestamp-c_timestamp) / 3600))
		} else if now_timestamp-c_timestamp > 60 {
			unit = "分钟前"
			num = int(math.Floor(float64(now_timestamp-c_timestamp) / 60))
		} else {
			unit = "秒前"
			num = int(math.Floor(float64(now_timestamp - c_timestamp)))
		}
	}
	return strconv.Itoa(num) + unit
}

func ForceCorrectTime(t time.Time) time.Time {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), loc)
}

// GetTodayZero 今天零点
func GetTodayZero(t time.Time) time.Time {
	loc, _ := time.LoadLocation("Asia/Shanghai")
	return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, loc)
}
func SplitDateRange(date_range string, sep string) (start_time_b string, start_time_e string) {
	str_arr := strings.Split(date_range, sep)
	start_time_b = strings.TrimSpace(str_arr[0])
	start_time_e = strings.TrimSpace(str_arr[1])
	return
}
func NullStringValue(value string) (val sql.NullString) {
	if value != "" {
		val.Valid = true
		val.String = value
	}
	return
}
func NullInt64Value(value int64) (val sql.NullInt64) {
	if value != 0 {
		val.Valid = true
		val.Int64 = value
	}
	return
}
func NullInt64StringValue(value string) (val sql.NullInt64, err error) {
	valInt, err := strconv.Atoi(value)
	if err != nil {
		return
	}
	return NullInt64Value(int64(valInt)), nil
}
func NullBoolValue(value string) (val sql.NullBool) {
	if value == "1" || value == "0" {
		val.Valid = true
		if value == "1" {
			val.Bool = true
		} else {
			val.Bool = false
		}
	}
	return
}
func NullTimeValue(value string) (val sql.NullTime) {
	if value != "" {
		the_time, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
		if err == nil {
			val.Valid = true
			val.Time = the_time
		}
	}
	return
}
func NullDateValue(value string) (val sql.NullTime) {
	if value != "" {
		the_time, err := time.ParseInLocation("2006-01-02", value, time.Local)
		if err == nil {
			val.Valid = true
			val.Time = the_time
		}
	}
	return
}
func NullTimeValueFormat(value sql.NullTime, format string) (val string) {
	if value.Valid {
		return ForceCorrectTime(value.Time).Format(format)
	}
	return
}

// Int64ToStringSlice int64切片转字符串切片
func Int64ToStringSlice(in_slice []int64) []string {
	var result []string
	for _, id := range in_slice {
		id_str := strconv.Itoa(int(id))
		result = append(result, id_str)
	}
	return result
}
func IntToStringSlice(in_slice []int) []string {
	var result []string
	for _, id := range in_slice {
		id_str := strconv.Itoa(id)
		result = append(result, id_str)
	}
	return result
}

// StringToInt64Slice 字符串切片转int64切片
func StringToInt64Slice(in_slice []string) []int64 {
	var result []int64
	for _, str := range in_slice {
		id, err := strconv.Atoi(str)
		if err == nil {
			result = append(result, int64(id))
		}
	}
	return result
}

// StringToNullFloatValue 字符串转浮点
func StringToNullFloatValue(value string) (val sql.NullFloat64) {
	if value != "" {
		if v, err := strconv.ParseFloat(value, 64); err == nil {
			val.Valid = true
			val.Float64 = v
		}
	}
	return
}

const (
	B  = 1
	KB = B << 10
	MB = KB << 10
	GB = MB << 10
	TB = GB << 10
	PB = TB << 10
)

// BeautifyFileSize 美化文件大小
func BeautifyFileSize(size_int int64) (num float64, unit string) {
	size := float64(size_int)
	if size < KB {
		num = size
		unit = "B"
	} else if size < MB {
		num = size / KB
		unit = "KB"
	} else if size < GB {
		num = size / MB
		unit = "MB"
	} else if size < TB {
		num = size / GB
		unit = "GB"
	} else if size < PB {
		num = size / TB
		unit = "TB"
	} else {
		num = size / PB
		unit = "PB"
	}
	return
}

// ReturnWebsiteLangText 返回网站语言文字
func ReturnWebsiteLangText(content string, lang string) string {
	if lang == "zh-CN" {
		return content
	}
	lang_map, exist := global.Language[lang]
	if !exist {
		b, _ := os.ReadFile(fmt.Sprintf("./dtcloud/lang/%s.json", lang))
		var m map[string]string
		json.Unmarshal(b, &m)
		global.Language[lang] = m
		lang_map = m
	}
	text, e := lang_map[content]
	if e {
		return text
	}
	return content
}

func GetPageList(page int64, total_page int64) (res []int64) {
	var page_num int64 = 5
	var start_page int64
	var end_page int64
	start_page = 1
	end_page = total_page
	if total_page > page_num {
		start_page = page - 2
		if start_page < 1 {
			start_page = 1
		}
		end_page = start_page + page_num - 1
	}
	for i := start_page; i <= end_page; i++ {
		res = append(res, i)
	}
	return
}

func DateStrToTime(input string, format string) time.Time {
	local, _ := time.LoadLocation("Asia/Shanghai")
	showTime, _ := time.ParseInLocation(format, input, local)
	return showTime
}

// GetTimeInterval 获取时间间隔（小时）
func GetTimeInterval(time1 time.Time, time2 time.Time) (hours float64) {
	timestamp1 := time1.Unix()
	timestamp2 := time2.Unix()
	hours = math.Abs(float64(timestamp1-timestamp2)) / 3600
	return
}

// GetYearMonthToDay 查询指定年份指定月份有多少天
// @params year int 指定年份
// @params month int 指定月份
func GetYearMonthToDay(year int, month int) int {
	// 有31天的月份
	day31 := map[int]struct{}{
		1:  struct{}{},
		3:  struct{}{},
		5:  struct{}{},
		7:  struct{}{},
		8:  struct{}{},
		10: struct{}{},
		12: struct{}{},
	}
	if _, ok := day31[month]; ok {
		return 31
	}
	// 有30天的月份
	day30 := map[int]struct{}{
		4:  struct{}{},
		6:  struct{}{},
		9:  struct{}{},
		11: struct{}{},
	}
	if _, ok := day30[month]; ok {
		return 30
	}
	// 计算是平年还是闰年
	if (year%4 == 0 && year%100 != 0) || year%400 == 0 {
		// 得出2月的天数
		return 29
	}
	// 得出2月的天数
	return 28
}

// GetJsonName 获取json名字
func GetJsonName(json_str string, lang string) string {
	var lan_name map[string]string
	cont, _ := io.ReadAll(strings.NewReader(json_str))
	json.Unmarshal(cont, &lan_name)
	if name, e := lan_name[lang]; e {
		return name
	}
	if name, e := lan_name["zh_CN"]; e {
		return name
	}
	if name, e := lan_name["en_US"]; e {
		return name
	}
	return ""
}

// SetJsonName 获取json名字
func SetJsonName(name string, lang string) string {
	var lan_name = map[string]string{lang: name}
	res, _ := json.Marshal(lan_name)
	return string(res)
}

// NumberHourToDateStr 小数小时转日期字符串
func NumberHourToDateStr(hour float64) string {
	hour_int := int(math.Floor(hour))
	left_float := hour - float64(hour_int)
	min_int := int(math.Ceil(left_float * 60))
	return fmt.Sprintf("%02d", hour_int) + ":" + fmt.Sprintf("%02d", min_int)
}

// DateStrToNumberHour 日期字符串转小时数字
func DateStrToNumberHour(hour_str string) float64 {
	hour_arr := strings.Split(hour_str, ":")
	hour, _ := strconv.Atoi(strings.TrimLeft(hour_arr[0], "0"))
	min, _ := strconv.Atoi(strings.TrimLeft(hour_arr[1], "0"))
	return float64(float64(hour) + float64(min)/60)
}

// IdCheck 身份证校验
func IdCheck(IdentificationId string) bool {
	if len(IdentificationId) != 18 && len(IdentificationId) != 15 {
		return false
	}
	if len(IdentificationId) == 18 {
		r, _ := regexp.MatchString(`^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[\dXx]$`, IdentificationId)
		if !r {
			return false
		}
	}
	if len(IdentificationId) == 15 {
		r, _ := regexp.MatchString(`^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}$`, IdentificationId)
		if !r {
			return false
		}
	}
	return true
}

// MobileCheck 手机号校验
func MobileCheck(mobile string) bool {
	match, err := regexp.MatchString(`^1[3456789]\d{9}$`, mobile)
	if err != nil {
		return false
	}
	if !match {
		return false
	}
	return true
}

// MailCheck 邮箱校验
func MailCheck(mail string) bool {
	match, err := regexp.MatchString(`^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$`, mail)
	if err != nil {
		return false
	}
	if !match {
		return false
	}
	return true
}

// GenerateTree 生成树形结构
func GenerateTree(data []global.FolderTree, pid int64) (res []global.FolderTree) {
	for _, v := range data {
		if v.ParentId == pid {
			res = append(res, global.FolderTree{
				Id:       v.Id,
				Name:     v.Name,
				ParentId: v.ParentId,
				Children: GenerateTree(data, v.Id),
				Data:     v.Data,
			})
		}
	}
	return res
}

// SendSocket 发送socket数据
func SendSocket(param map[string]string, message string) (err error) {
	header := map[string]string{}
	//发送socket
	socket_url := config.Conf.SocketUrl + "/message"

	post := map[string]string{
		"message": message,
	}
	_, err = HttpPost(socket_url, header, param, post)
	return
}

func ContainsIn64Duplicate2(nums []int64) bool {
	hash := make(map[int64]bool)
	for _, v := range nums {
		if hash[v] == true {
			return true
		} else {
			hash[v] = true
		}
	}
	return false
}
